#pragma once

#include <functional>
#include <map>
#include <queue>
#include <vector>

#include "src/graph.h"
#include "src/utils.h"

namespace pathfind {
class Astar {
private:
  struct ComparerCost {
    bool operator()(const PairPositionCost &ppc1, const PairPositionCost &ppc2);
  };

  typedef std::priority_queue<PairPositionCost, std::vector<PairPositionCost>,
                              ComparerCost>
      AstarPriorityQueue;

public:
  explicit Astar(std::unordered_map<IntPoint, int> map, int width, int height);

  std::vector<IntPoint> finding(const IntPoint &start, const IntPoint &end);

  IntPoint get_neaest_point(const IntPoint &p, const int32_t range) const;

private:
  void reconstruct_path();
  void optimizing();

private:
  Graph graph_;
  IntPoint start_;
  IntPoint end_;

  std::vector<IntPoint> visited_pos_;
  std::vector<IntPoint> optimized_pos_;

  // variables use in finding.
  AstarPriorityQueue frontier_;
  std::map<IntPoint, float> cost_so_far_;
  std::map<IntPoint, IntPoint> came_from_;
  std::unordered_map<IntPoint, float> neighbours_;
};
}
